/*
 * Copyright (C) 2007 
 *  Written by C.Stefano
 */
namespace GenericServiceInstaller
{
  using System;
  using System.Runtime.InteropServices;

  /// <summary>
  /// Adapted from  Installing a Service Programmatically
  ///  By Sachin Nigam September 04, 2003 
  /// http://www.c-sharpcorner.com/UploadFile/sachin.nigam/InstallingWinServiceProgrammatically11262005061332AM/InstallingWinServiceProgrammatically.aspx
  /// </summary>
  public sealed class ServiceInstaller
  {

    public static bool InstallService(
      string name, 
      string displayName,
      string serviceApplication)
    {
      bool success = false;
      IntPtr sc_handle = Win32.OpenSCManager(null, null, Win32.SC_MANAGER_CREATE_SERVICE);
      if(sc_handle.ToInt32()!=0)
      {
        IntPtr sv_handle = Win32.CreateService
          (
            sc_handle,
            name,
            displayName,
            Win32.SERVICE_ALL_ACCESS,
            Win32.SERVICE_WIN32_OWN_PROCESS, 
            Win32.SERVICE_AUTO_START,
            Win32.SERVICE_ERROR_NORMAL,
            serviceApplication,
            null,
            0,
            null,
            null,
            null
          );

        if(sv_handle.ToInt32()!=0)
        {
          Win32.CloseServiceHandle(sv_handle);
          success = true;
        }
        Win32.CloseServiceHandle(sc_handle);
      }
      return success;
    }

    public static bool UnInstallService(string name)
    {
      bool success = false;
      IntPtr sc_hndl = Win32.OpenSCManager(null, null, Win32.GENERIC_WRITE);
      if(sc_hndl.ToInt32()!=0)
      {
        IntPtr svc_hndl = Win32.OpenService(sc_hndl, name, Win32.DELETE);
        if(svc_hndl.ToInt32()!=0)
        {
          int i = Win32.DeleteService(svc_hndl);
          if(i!=0)
            success = true;
          Win32.CloseServiceHandle(svc_hndl);
        }
        Win32.CloseServiceHandle(sc_hndl);
      }
      return success;
    }

    internal sealed class Win32
    {

      [DllImport("advapi32.dll")]
      public static extern IntPtr OpenSCManager(string lpMachineName,string lpSCDB, int scParameter);

      [DllImport("Advapi32.dll")]
      public static extern IntPtr CreateService(IntPtr SC_HANDLE,string lpSvcName,string lpDisplayName, int dwDesiredAccess,int dwServiceType,int dwStartType,int dwErrorControl,string lpPathName, string lpLoadOrderGroup,int lpdwTagId,string lpDependencies,string lpServiceStartName,string lpPassword);

      [DllImport("advapi32.dll")]
      public static extern void CloseServiceHandle(IntPtr SCHANDLE);
    
      [DllImport("advapi32.dll")]
      public static extern int StartService(IntPtr SVHANDLE,int dwNumServiceArgs,string lpServiceArgVectors);
    
      [DllImport("advapi32.dll",SetLastError=true)]
      public static extern IntPtr OpenService(IntPtr SCHANDLE,string lpSvcName,int dwNumServiceArgs);
    
      [DllImport("advapi32.dll")]
      public static extern int DeleteService(IntPtr SVHANDLE);
    
      [DllImport("kernel32.dll")]
      public static extern int GetLastError();

      public const int GENERIC_WRITE = 0x40000000;
      public const int SC_MANAGER_CREATE_SERVICE = 0x0002;
      public const int SERVICE_WIN32_OWN_PROCESS = 0x00000010;
      public const int SERVICE_DEMAND_START = 0x00000003;
      public const int SERVICE_ERROR_NORMAL = 0x00000001;
      public const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
      public const int SERVICE_QUERY_CONFIG = 0x0001;
      public const int SERVICE_CHANGE_CONFIG = 0x0002;
      public const int SERVICE_QUERY_STATUS = 0x0004;
      public const int SERVICE_ENUMERATE_DEPENDENTS = 0x0008;
      public const int SERVICE_START =0x0010;
      public const int SERVICE_STOP =0x0020;
      public const int SERVICE_PAUSE_CONTINUE =0x0040;
      public const int SERVICE_INTERROGATE =0x0080;
      public const int SERVICE_USER_DEFINED_CONTROL =0x0100;
      public const int SERVICE_ALL_ACCESS = (
        STANDARD_RIGHTS_REQUIRED |
        SERVICE_QUERY_CONFIG |
        SERVICE_CHANGE_CONFIG |
        SERVICE_QUERY_STATUS |
        SERVICE_ENUMERATE_DEPENDENTS |
        SERVICE_START |
        SERVICE_STOP |
        SERVICE_PAUSE_CONTINUE |
        SERVICE_INTERROGATE |
        SERVICE_USER_DEFINED_CONTROL
        );
      public const int SERVICE_AUTO_START = 0x00000002;
      public const int DELETE = 0x10000;
    
    }


  }

}
